import { tryOnUnmounted } from '@vueuse/core';

export class ReadyPromise {
  constructor() {
    this.state = new Promise((resolve, reject) => {
      this.done = () => resolve();
      this.fail = () => reject();
    });
    this.destroy = () => {
      this.fail();
    };
    tryOnUnmounted(() => this.destroy());
  }
}

export class PromiseState {
  constructor() {
    let _resolve = null;
    let _reject = null;
    let callbacks = { ok: [], fail: [] };

    this.state = new Promise((resolve, reject) => {
      _resolve = resolve;
      _reject = reject;
    });
    this.onReady = function (callback) {
      if (typeof callback === 'function') callbacks.ok.push(callback);
    };
    this.onFail = function (callback) {
      if (typeof callback === 'function') callbacks.fail.push(callback);
    };
    this.ready = function (res) {
      typeof _resolve === 'function' && _resolve(res);
      if (callbacks && callbacks.ok && callbacks.ok.length) {
        callbacks.ok.forEach((callback) => callback(res));
      }
    };
    this.fail = function (e) {
      typeof _reject === 'function' && _reject(e);
      if (callbacks && callbacks.fail && callbacks.fail.length) {
        callbacks.fail.forEach((callback) => callback(e));
      }
    };
    this.run = async (handle) => {
      try {
        let res = await handle();
        this.ready(res);
      } catch (e) {
        this.fail(e);
      }
    };
    this.destroy = function () {
      callbacks.ok.length = 0;
      callbacks.fail.length = 0;
      _reject();
      _reject = _resolve = callbacks = null;
    };
    tryOnUnmounted(() => this.destroy());
  }
}
